package com.study;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author:李雄
 * @ClassName:StreamAPITest1
 * @Description:Stream的中间操作
 * @createTime:2022-08-22 6:24
 */
public class StreamAPITest1 {
    //1筛选与切片
    /*
     * filter(Predicate p)--接收Lambda,从流中排除某些元素。
     * limit（n）--截断流，使其元素不超这过给定数量
     * skip（n）--跳过元素，返回一个扔掉了前n个元素的流。若流中元素不足n个，则返回一个
     * distinct（）--筛选，通过流所生成的元素的hashCode（）和equals（）去除重复元素。
     * */
    @Test
    public void test1() {
        //filter(Predicate p)--接收Lambda,从流中排除某些元素。
        List<EmployeeData> list = new ArrayList<>();
        list.add(new EmployeeData(1001, "马化腾", 34, 6000.83));
        list.add(new EmployeeData(1002, "雷军", 12, 9800.00));
        list.add(new EmployeeData(1003, "刘强东", 33, 5800.12));
        list.add(new EmployeeData(1004, "比尔盖茨", 26, 10900.00));
        list.add(new EmployeeData(1005, "马云", 65, 1000000.00));
        list.add(new EmployeeData(1006, "李彦宏", 35, 4000.00));
        //查询员工表中工资大于7000的员工信息。
        list.stream().filter(e -> e.getSalary() > 7000).forEach(System.out::println);
        System.out.println("===================================");
        //limit（n）--截断流，使其元素不超这过给定数量
        list.stream().limit(3).forEach(System.out::println);
        System.out.println("===================================");
        //skip（n）--跳过元素，返回一个扔掉了前n个元素的流。若流中元素不足n个，则返回一个空流，与limit（n）互补。
        list.stream().skip(10).forEach(System.out::println);
        System.out.println("===================================");
        List<Integer> list1 = new ArrayList<>();
        list1.add(1);
        list1.add(1);
        list1.add(2);
        list1.add(3);
        list1.add(4);
        list1.add(4);
        list1.stream().distinct().forEach(System.out::println);
    }

    //映射
    @Test
    public void test2() {
        //map(Function f)--接收一个函数作为参数，将元素转换成其他形式或提取信息
        // ，该函数会被应用到每个元素上，并将其映射成一个新的元素。
        List<String> list1 = Arrays.asList("aa", "bb", "cc", "DD");
        list1.stream().map(str -> str.toUpperCase()).forEach(System.out::println);
        List<EmployeeData> list = new ArrayList<>();
        list.add(new EmployeeData(1001, "马化腾", 34, 6000.83));
        list.add(new EmployeeData(1002, "雷军", 12, 9800.00));
        list.add(new EmployeeData(1003, "刘强东", 33, 5800.12));
        list.add(new EmployeeData(1004, "比尔盖茨", 26, 10900.00));
        list.add(new EmployeeData(1005, "马云", 65, 1000000.00));
        list.add(new EmployeeData(1006, "李彦宏", 35, 4000.00));
        //获取员工名名字长度大于2的员工
        list.stream().map(e -> e.getName()).filter(name -> name.length() > 2).forEach(System.out::println);

        Stream<Stream<Character>> streamStream = list1.stream().map(StreamAPITest1::fromStringToStream);
        streamStream.forEach(s -> {
            s.forEach(System.out::println);
        });
        System.out.println();
        //flatMap(Function f)接受一个函数作为参数，将流中的每个值都换成另一个流，然后把所有流转换成一个大流。
        list1.stream().flatMap(StreamAPITest1::fromStringToStream).forEach(System.out::println);

    }

    public static Stream<Character> fromStringToStream(String str) {
        ArrayList<Character> list = new ArrayList<>();
        for (Character c : str.toCharArray()) {
            list.add(c);
        }
        return list.stream();
    }

    @Test
    public void test3() {
        ArrayList list1 = new ArrayList();
        list1.add(1);
        list1.add(2);
        list1.add(3);

        ArrayList list2 = new ArrayList();
        list2.add(4);
        list2.add(5);
        list2.add(6);

        //list2.add(list2);map映射与其类似
        list2.addAll(list2);//flatMap()与其类似

        System.out.println(list1);

    }

    //排序
    @Test
    public void test4() {
        //sorted()--自然排序
        List<Integer> list1 = Arrays.asList(12, 43, 65, 34, 87, 0, -98, 7);
        list1.stream().sorted().forEach(System.out::println);

        List<EmployeeData> list = new ArrayList<>();
        list.add(new EmployeeData(1001, "马化腾", 34, 6000.83));
        list.add(new EmployeeData(1002, "雷军", 12, 9800.00));
        list.add(new EmployeeData(1003, "刘强东", 33, 5800.12));
        list.add(new EmployeeData(1004, "比尔盖茨", 26, 10900.00));
        list.add(new EmployeeData(1005, "马云", 65, 1000000.00));
        list.add(new EmployeeData(1006, "李彦宏", 35, 4000.00));
        //抛异常EmployeeData类没有实现Comparable接口
//        list.stream().sorted().forEach(System.out::println);


        //sorted(Comparator com)--定制排序
        list.stream().sorted((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge()))
                .forEach(System.out::println);
    }

    //终止操作
    //排序
    @Test
    public void test5() {
        List<EmployeeData> list = new ArrayList<>();
        list.add(new EmployeeData(1001, "马化腾", 34, 6000.83));
        list.add(new EmployeeData(1002, "雷军", 12, 9800.00));
        list.add(new EmployeeData(1003, "刘强东", 33, 5800.12));
        list.add(new EmployeeData(1004, "比尔盖茨", 26, 10900.00));
        list.add(new EmployeeData(1005, "马云", 65, 1000000.00));
        list.add(new EmployeeData(1006, "李彦宏", 35, 4000.00));
        //1.匹配与查找
//        * allMatch(Predicate p)--检查是否匹配所有元素。
        //练习是否所有员工的年龄都大于18
        System.out.println(list.stream().allMatch(e -> e.getAge() > 18));
//        * anyMatch(Predicate p)--检查是否至少匹配一个元素。
        System.out.println(list.stream().anyMatch(e -> e.getAge() > 18));
//        * noneMatch(Predicate p)--检查是否没有匹配的元素。
        //是否有姓雷的员工
        System.out.println(list.stream().noneMatch(e -> e.getName().startsWith("雷")));
//        * findFirst()--返回第一个元素
        Optional<EmployeeData> first = list.stream().findFirst();
        System.out.println(first);
//        * findAny()--返回当前流中的任意元素
        System.out.println(list.stream().findAny());
//        * count--返回流中元素的总个数,返回值类型为long
        System.out.println(list.stream().count());
//        * max(Comparator c)--返回流中最大值
        //返回工资最高的
        System.out.println(list.stream().map(e -> e.getSalary()).max(Double::compare));
//        * min(Comparator c)--返回流中最小值
        System.out.println(list.stream().map(e -> e.getSalary()).min(Double::compare));
//        * forEach(Consumer c)--内部迭代
        list.stream().forEach(System.out::println);
    }
    //终止操作
    //规约
    @Test
    public void test6(){
         //reduce(T identity,BinaryOperator)--可以将流中元素反复结合起来，得到一个值。第一参数为初始值。返回一个T
        //计算1-10的自然数的和
        List<Integer> list1 = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        System.out.println(list1.stream().reduce(0, Integer::sum)+"\n");

        //reduce(BinaryOperator)--可以将流中元素反复结合起来，得到一个值。返回Optional<T>
        //计算公司员工工资的总和
        List<EmployeeData> list = new ArrayList<>();
        list.add(new EmployeeData(1001, "马化腾", 34, 6000.83));
        list.add(new EmployeeData(1002, "雷军", 12, 9800.00));
        list.add(new EmployeeData(1003, "刘强东", 33, 5800.12));
        list.add(new EmployeeData(1004, "比尔盖茨", 26, 10900.00));
        list.add(new EmployeeData(1005, "马云", 65, 1000000.00));
        list.add(new EmployeeData(1006, "李彦宏", 35, 4000.00));
        System.out.println(list.stream().map(e -> e.getSalary()).reduce(Double::sum));
    }
    //终止操作
    //收集
    @Test
    public void test7(){
        //collect(Collect c):将流转换成其他形式。接收一个Collector接口的实现，用于给Stream中元素做汇总的方法
        //员工信息返回为一个List或Set
        List<EmployeeData> list = new ArrayList<>();
        list.add(new EmployeeData(1001, "马化腾", 34, 6000.83));
        list.add(new EmployeeData(1002, "雷军", 12, 9800.00));
        list.add(new EmployeeData(1003, "刘强东", 33, 5800.12));
        list.add(new EmployeeData(1004, "比尔盖茨", 26, 10900.00));
        list.add(new EmployeeData(1005, "马云", 65, 1000000.00));
        list.add(new EmployeeData(1006, "李彦宏", 35, 4000.00));
        List<EmployeeData> collect = list.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toList());
        collect.forEach(System.out::println);
    }

}
